package fiado.dao.memory;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import fiado.bean.Pessoa;
import fiado.exception.DaoException;


public class PessoaDAO {

	public static final List<Pessoa> tabela = Collections.synchronizedList(new ArrayList<Pessoa>());

	public static int nextValue = 10;
	
	static {
		try {
			Pessoa p = criarPessoa(5, "Johann Sebastian", "Bach", "31/03/1685", "28/07/1750");
			PessoaDAO.tabela.add(p);
			p = criarPessoa(7, "Johannes", "Kepler", "27/12/1571", "15/11/1630");
			PessoaDAO.tabela.add(p);
			p = criarPessoa(8, "James", "Gosling", "19/05/1955", null);
			PessoaDAO.tabela.add(p);
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}

	private static Pessoa criarPessoa(
			int id, 
			String prenome, 
			String sobrenome, 
			String dtNasc, 
			String dtFalec) throws ParseException {
		Pessoa p = new Pessoa();
		p.setId(id);
		p.setPrenome(prenome);
		p.setSobrenome(sobrenome);
		if (dtNasc != null) {
			p.setDataNascimento(new SimpleDateFormat("dd/MM/yyyy").parse(dtNasc));	
		}
		if (dtFalec != null) {
			p.setDataFalecimento(new SimpleDateFormat("dd/MM/yyyy").parse(dtFalec));
		}
		return p;
	}
	
	private static List<Pessoa> copy(List<Pessoa> lista) {
		List<Pessoa> listaCopia = new ArrayList<Pessoa>();
		for (Pessoa p : lista) {
			listaCopia.add(copy(p));
		}
		return listaCopia;
	}
	
	private static Pessoa copy(Pessoa p) {
		Pessoa copy = new Pessoa();
		copy.setId(p.getId());
		copy.setPrenome(p.getPrenome());
		copy.setSobrenome(p.getSobrenome());
		copy.setDataNascimento(p.getDataNascimento());
		copy.setDataFalecimento(p.getDataFalecimento());
		return copy;
	}
	
	private int getProximoValorSequence() throws DaoException {
		return nextValue++;
	}
	
	/**
	 * Este metodo retorna uma lista com todos os objetos pessoa armazenados
	 * @return
	 * @throws DaoException 
	 */
	public List<Pessoa> buscarTodos() throws DaoException {
		return copy(PessoaDAO.tabela);
	}

	/**
	 * Este metodo retorna uma lista com todos os objetos pessoa armazenados
	 * que possuam <nome> no campo prenome ou no campo sobrenome
	 * @return
	 * @throws DaoException 
	 */
	public List<Pessoa> buscarPorNome(String nome) throws DaoException {
		nome = ".*" + nome + ".*";
		List<Pessoa> lista = new ArrayList<Pessoa>();

		for (Pessoa p : PessoaDAO.tabela) {
			if (p.getPrenome().matches(nome) || p.getSobrenome().matches(nome)) {
				lista.add(copy(p));
			}
		}

		return lista;
	}
	
	/**
	 * Este metodo retorna o objeto pessoa de acordo com o id
	 * @return
	 * @throws DaoException 
	 */
	public Pessoa buscarPorId(int idPessoa) throws DaoException {
		for (Pessoa p : PessoaDAO.tabela) {
			if (p.getId() == idPessoa) {
				return copy(p);
			}
		}
		return null;
	}
	
	/**
	 * Este metodo apaga o objeto pessoa de acordo com o id
	 * @throws DaoException 
	 */
	public void apagar(int idPessoa) throws DaoException {
		Iterator<Pessoa> it = PessoaDAO.tabela.iterator();
		while (it.hasNext()) {
			Pessoa p = it.next();
			if (p.getId() == idPessoa) {
				it.remove();
			}
		}
	}	
	
	/**
	 * Este metodo apaga o objeto pessoa
	 * @throws DaoException 
	 */
	public void apagar(Pessoa pessoa) throws DaoException {
		apagar(pessoa.getId());
	}
	
	/**
	 * Este metodo salva o objeto pessoa 
	 * @throws DaoException 
	 */
	public void salvar(Pessoa pessoa) throws DaoException {
		Iterator<Pessoa> it = PessoaDAO.tabela.iterator();
		while (it.hasNext()) {
			Pessoa p = it.next();
			if (p.getId() == pessoa.getId()) {
				it.remove();
			}
		}
		PessoaDAO.tabela.add(copy(pessoa));
	}
	
	/**
	 * Este metodo cria o objeto pessoa e retorna o objeto criado com o novo id
	 * preenchido
	 * @throws DaoException 
	 */
	public void criar(Pessoa pessoa) throws DaoException {
		int novoIdPessoa = getProximoValorSequence();
		pessoa.setId(novoIdPessoa);
		PessoaDAO.tabela.add(copy(pessoa));
	}
}
